package pers.kw.server.user.service;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.kw.contants.RedissonContants;
import pers.kw.crm.dto.UserDto;
import pers.kw.dozer.BeanMapper;
import pers.kw.entity.PageDto;
import pers.kw.entity.TokenDto;
import pers.kw.exceptions.BizException;
import pers.kw.protocol.TokenContext;
import pers.kw.server.user.persist.dao.CustUserDao;
import pers.kw.server.user.dto.QueryUserReqDto;
import pers.kw.server.user.persist.entity.CustUserDO;
import pers.kw.server.user.persist.mapper.CustUserMapper;
import pers.kw.utils.DoWrapUtil;
import pers.kw.utils.SnowFlake;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserService {

    @Resource
    private CustUserDao custUserDao;

    @Resource
    private CustUserMapper custUserMapper;

    @Resource
    private BeanMapper beanMapper;

    @Resource
    private RedissonClient redissonClient;

    public PageDto<UserDto> pageQueryUserList(QueryUserReqDto reqDto) {
        log.info("分页查询user列表，入参:{}", JSON.toJSONString(reqDto));
        Page<UserDto> selectResult = PageHelper.startPage(reqDto.getPageNum(), reqDto.getPageSize());
        custUserMapper.pageQueryUserList(reqDto);
        PageDto<UserDto> page = DoWrapUtil.page(selectResult);
        log.info("分页查询user列表，出参:{}", JSON.toJSONString(page));
        return page;
    }

    public UserDto getUserInfo() {
        TokenDto current = TokenContext.current();
        if (current == null) {
            throw new BizException("登录信息已失效");
        }
        String userNo = current.getUserNo();
        CustUserDO custUserDO = custUserDao.findByUserNo(userNo);
        beanMapper.convert(custUserDO, UserDto.class);
        return beanMapper.convert(custUserDO, UserDto.class);
    }

    public UserDto getUserByUserNo(String userNo) {
        log.info("获取用户信[{}]息start...", userNo);
        CustUserDO custUserDO = custUserDao.findByUserNo(userNo);
        UserDto userDto = beanMapper.convert(custUserDO, UserDto.class);
        log.info("获取用户信[{}]息end...出参：{}", userNo, JSON.toJSONString(userDto));
        return userDto;
    }

    public String addUserUseLock(UserDto reqDto) {
        RLock rLock = redissonClient.getLock(RedissonContants.USERNAME_LOCK_KEY);
        rLock.lock();
        //最好指定过期时间
        //lock有很多重载方法，具体看文档
        log.info("用户添加，加锁成功。。。");
        try {
            UserService userService = (UserService) AopContext.currentProxy();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return userService.insertUser(reqDto);
        } finally {
            try {
                rLock.unlock();
                log.info("用户添加，自动释放锁成功。。。");
            } catch (Exception e) {
                log.error("用户添加，自动释放锁失败", e);
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public String insertUser(UserDto reqDto) {
        log.info("crm新增用户start...入参：{}", JSON.toJSONString(reqDto));
        //校验userName不可重复，（并发场景，需要锁）
        CustUserDO oldUser = custUserDao.findByUserName(reqDto.getUserName());
        if (oldUser != null) {
            throw new BizException("用户昵称已存在");
        }

        CustUserDO custUserDO = beanMapper.convert(reqDto, CustUserDO.class);
        custUserDO.setUserNo(SnowFlake.getSnowId());
        DoWrapUtil.insert(custUserDO, false, false);
        custUserDao.save(custUserDO);
        log.info("crm新增用户end...出参：{}", JSON.toJSONString(custUserDO));
        return custUserDO.getUserNo();
    }
}
